This page last changed on Oct 20, 2006 by cholmes.

Introduction

An output format is what form Geoserver returns requested data. By default, a getFeature request returns the feature(s) in GML2. Another output type can be Shapefile.

To specify what output format you want returned by Geoserver, just append the outputformat=mytype argument to the URL.

http://localhost:8080/geoserver/wfs?
request=getfeature&
service=wfs&
version=1.0.0&
typename=states&
outputformat=SHAPE-ZIP

Here are some output formats that come with Geoserver:

  • GML2
  • GML2-GZIP
  • SHAPE-ZIP
Note

This is an advanced tutorial. It tells you where to put your files and what interfaces you will have to implement. It assumes you are moderately experienced with java and have used the java.IO.OutputStream class.

Overview

There are two files you must add, and one you must modify.

  1. Create MyFormatFeatureResponseDelegate.java
  2. Create MyFormatFeatureResponseDelegateFactory.java
  3. Modify org.vfny.geoserver.wfs.FeatureResponseDelegateProducerSpi

STEP 1: Create MyFormatFeatureResponseDelegate.java

In the package org.vfny.geoserver.wfs.responses, create your class MyFormatFeatureResponseDelegate.java

It must implement the FeatureResponseDelegate interface:

public interface FeatureResponseDelegate 
{
    boolean canProduce(String outputFormat);

    void prepare(String outputFormat, GetFeatureResults results)
        throws IOException;

    String getContentType(GeoServer gs);

    String getContentEncoding();

    void encode(OutputStream output) throws ServiceException, IOException;
}

Also, create a global variable called results that is a GetFeatureResults object.

private GetFeatureResults results;

STEP 1.1: canProduce(String outputFormat)

This is a very simple method. It basically looks at the output format string passed in and checks to see if this class can handle it. Here is an example of how the GML FeatureResponseDelegate handles it:

public boolean canProduce(String outputFormat) 
{
    return "GML2".equalsIgnoreCase(outputFormat)
        || "GML2-GZIP".equalsIgnoreCase(outputFormat);
}

STEP 1.2: prepare(String outputFormat, GetFeatureResults results)

The prepare method is called before any output is processed. It is used to set up Geoserver for the selected output format. In here you want to do all your initial setup in order to throw any errors early, before you start pulling out the data. You also save the results passed in from the parameters. This method doesn't have to do anything fancy, and your output format might not have anything it can prepare. It is just here to give the programmer a chance to detect errors early on, and possibly handle them, and to hold onto the results from the query. So if you want, you can leave it blank except for the one line:

this.results = results;

Here is an example from the ShapeFeatureResponseDelegate class:

public void prepare(String outputFormat, GetFeatureResults results) throws IOException 
    {
        this.results = results;

        if (results == null) {
            throw new IllegalStateException(
                "It seems prepare() has not succeed. <results> is null");
        }
        
        tempDir = System.getProperty("java.io.tmpdir");
        
        if (tempDir == null) {
        	throw new NullPointerException("<tempDir> is null. " +
        			"There is a problem with the java.io.tempdir directory.");
        }
    }

STEP 1.3: getContentType(GeoServer gs)

TODO: Fill in this step.
For now, just have your method return this:

return gs.getMimeType();

STEP 1.4: getContentEncoding()

This method will return a string that describes how the content has been encoded, if it has been encoded at all. If it has not been encoded, have it return null.

Here is an example from the ShapeFeatureResponseDelegate class:

public String getContentEncoding() {
    return "zip";
}

STEP 1.5: encode(OutputStream output)

Here is where the actual output occurs. All of the data must be written out to the OutputStream. I can't go into too much detail as what you have to do here, because it depends on your output format. But take a look at the Shapefile and GML output formats.

Note: Use close()

It is important to note that if you open any other output streams, not the one passed in but if you make another one, that you close them.

STEP 2: Create MyFormatFeatureResponseDelegateFactory.java

In the package org.vfny.geoserver.wfs.responses, create your class MyFormatFeatureResponseDelegateProducer.java

Your class must implement FeatureResponseDelegateProducerSpi:

public interface FeatureResponseDelegateProducerSpi extends Factory
{
    String getName();

    Set getSupportedFormats();

    boolean isAvailable();

    boolean canProduce(String format);

    FeatureResponseDelegate createFeatureDelegateProducer(String format)
        throws IllegalArgumentException;

Also, create a global static variable that is a java.util.HashSet.
In it, store the possible types that this factory can handle. Here is an example from GML2FeatureResponseDelegateFactory:

static HashSet supportedFormats = new HashSet();
	
static{
    supportedFormats.add("GML2");
    supportedFormats.add("GML2-GZIP");
}

STEP 2.1: getName()

This method returns a descriptive name for the factory instance. For example in ShapefileFeatureResponseDelegateFactory:

public String getName() {
    return "Shapefile Output (compressed in a zip file)";
}

STEP 2.2: getSupportedFormats()

This method returns all the supported output types. All it has to look like is this:

public Set getSupportedFormats() 
{
    return supportedFormats;
}

Just return the HashSet you created back in step 2.0.

STEP 2.3: isAvailable()

This method determines whether this factory is able to produce producer instances.
Both ShapefileFeatureResponseDelegateFactory and GML2FeatureResponseDelegateFactory just return true.

STEP 2.4: canProduce(String format)

Returns true if this factory can create the specified output format.
It is the same as the canProduce() method from your MyFormatFeatureResponseDelegate class

STEP 2.5: createFeatureDelegateProducer(String format)

This method will create a new MyFormatFeatureResponseDelegate. It should check to see if the format can be created, and then create the object.
Here is what the method looks like in GML2FeatureResponseDelegateFactory:

public FeatureResponseDelegate createFeatureDelegateProducer(String format) throws IllegalArgumentException 
{
	if (canProduce(format))
		return new GML2FeatureResponseDelegate();
	throw new IllegalArgumentException("cannot produce "+format);
}

STEP 3: Modify FeatureResponseDelegateProducerSpi

Navigate to your Geoserver source directory, then to META-INF\services.
Open up the file org.vfny.geoserver.wfs.FeatureResponseDelegateProducerSpi

Add the line:

org.vfny.geoserver.wfs.responses.MyFormatFeatureResponseDelegateFactory

Test It Out

Try it out by using the below URL, but change it to point to your running Geoserver instance and to use your new output format.

http://localhost:8080/geoserver/wfs?
request=getfeature&
service=wfs&
version=1.0.0&
typename=states&
outputformat=SHAPE-ZIP

The outputformat string should be the same as the strings in the canProduce(String format) methods you created.

Document generated by Confluence on Jan 16, 2008 23:26